package com.luoyi.util.ovs;

import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSON;
import com.luoyi.util.ovs.annotation.DataOut;
import com.luoyi.util.ovs.model.IndexFlowVo;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.apache.commons.lang3.reflect.FieldUtils.getAllFields;

/**
 *
 *
 * @author tail7
 */
public class AnnotationUtil {

    public static void main(String[] args) {
        List<DataOut> annotationFields = getAnnotationFields(IndexFlowVo.class, DataOut.class);
        System.out.println(JSON.toJSONString(annotationFields));
    }

    /**
     * 获取类中指定注解的所有字段注解
     *
     * @param clazz      需要处理的类的Class对象
     * @param annotation 指定的注解类型
     * @param <N>        注解类型N，必须是Annotation的子类
     * @return 包含指定注解的字段注解列表如果找不到，返回空列表
     */
    public static <N extends Annotation> List<N> getAnnotationFields(Class<?> clazz, Class<N> annotation) {
        // 获取类中所有声明的getter方法
        Set<Method> methods = getDeclaredGetMethods(clazz);
        // 创建列表，用于存储找到的指定注解实例
        List<N> list = new ArrayList<>();
        // 获取类中所有字段，包括私有和受保护的字段
        Field[] fields = getAllFields(clazz);

        // 遍历所有字段，查找具有指定注解的字段，并添加到列表中
        for (Field field : fields) {
            if (null != field.getAnnotation(annotation)) {
                list.add(field.getAnnotation(annotation));
            }
        }

        // 遍历所有getter方法，查找具有指定注解的方法，并添加到列表中
        for (Method method : methods) {
            if (null != method.getAnnotation(annotation)) {
                list.add(method.getAnnotation(annotation));
            }
        }

        // 返回找到的指定注解列表
        return list;
    }

    private static Set<Method> getDeclaredGetMethods(Class<?> clazz) {
        Method[] methods = ReflectUtil.getMethods(clazz);
        // 数组转set
        Set<Method> methodsSet = new HashSet<>();
        for (Method method : methods) {
            if (method.getName().startsWith("get") && method.getParameterCount() == 0) {
                methodsSet.add(method);
            }
        }
        return methodsSet;
    }
}
